home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 059 (1989-12)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 059 (1989-12)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / Utils / cut.c < prev    next >
C/C++ Source or Header  |  1989-11-14  |  8KB  |  343 lines

  1. /*
  2. */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <error.h>
  8. #include <ios1.h>
  9. #include <proto/dos.h>
  10.  
  11. #define TRUE 1
  12. #define FALSE 0
  13.  
  14. #define WARN 10
  15. #define ERROR 20
  16.  
  17. #define MAXLEN 255 /* Max line length */
  18. #define MAXDELIM 20
  19. #define MAXLIST 260 /* > MAXLEN */
  20.  
  21. #define isoctal(c) ((c) >= '0' && (c) <= '7')
  22. #define hexdigit(c) ((c) <= '9' ? (c) - '0' : tolower(c) - 'a')
  23.  
  24. extern char *optarg;
  25. extern int opterr, optind;
  26. extern int _bufsiz;
  27. int err;
  28.  
  29. char delims[MAXDELIM] = "\t ";
  30. int suppress, column, field, delim, unique;
  31. char use[MAXLIST];
  32.  
  33. int nextfield(char *field, char *line, char **pos)
  34. {
  35.     static int done;
  36.     char *end;
  37.  
  38.     if (*pos == NULL)
  39.     {
  40.         if (unique)
  41.             *pos = line;
  42.         else
  43.             *pos = line + strspn(line, delims);
  44.         done = FALSE;
  45.     }
  46.     if (done) return EOF;
  47.  
  48.     end = strpbrk(*pos, delims);
  49.  
  50.     if (!end)
  51.     {
  52.         strcpy(field, *pos);
  53.         done = TRUE;
  54.  
  55.         return '\0';
  56.     }
  57.     else
  58.     {
  59.         field[end - *pos] = '\0';
  60.         strncpy(field, *pos, end - *pos);
  61.         if (unique)
  62.             *pos = end + 1;
  63.         else
  64.             *pos = end + strspn(end, delims);
  65.  
  66.         return *end;
  67.     }
  68. }
  69.  
  70. char *extract_list(char *to, char *from)
  71. {
  72.     char *ret = to;
  73.     int pos = 0;
  74.  
  75.     while (pos < MAXLIST - 1 && from[pos])
  76.     {
  77.         if (use[pos + 1])
  78.            *to++ = from[pos];
  79.         pos++;
  80.     }
  81.     *to++ = '\n'; /* Shouldn't be here, but ... */
  82.     *to = '\0';
  83.     return ret;
  84. }
  85.  
  86. char *expand_tabs(char *dest, char *src, int maxlen)
  87. {
  88.     int spos = 0, dpos = 0;
  89.  
  90.     while (src[spos] && dpos < maxlen - 1)
  91.     {
  92.         if (src[spos] != '\t') dest[dpos++] = src[spos++];
  93.         else
  94.         {
  95.             int pad = 8 - spos % 8;
  96.  
  97.             if (dpos + pad <= maxlen - 1)
  98.             {
  99.                 memset(&dest[dpos], ' ', 8 - spos % 8);
  100.                 dpos += pad;
  101.                 spos++;
  102.             }
  103.             else break;
  104.         }
  105.     }
  106.     dest[dpos] = '\0';
  107.     return dest;
  108. }
  109.  
  110. void cut(FILE *file)
  111. {
  112.     char line[MAXLEN + 1], detabbed[MAXLEN + 1], out[MAXLEN + 2];
  113.  
  114.     line[MAXLEN] = '\0';
  115.  
  116.     while (errno == 0 && fgets(line, MAXLEN, file) && errno == 0)
  117.     {
  118.         int l = strlen(line);
  119.  
  120.         if (l > 0 && line[l - 1] == '\n') line[l - 1] = '\0';
  121.  
  122.         if (column)
  123.         {
  124.             expand_tabs(detabbed, line, MAXLEN + 1);
  125.             extract_list(out, detabbed);
  126.             fputs(out, stdout);
  127.         }
  128.         else
  129.             if (strpbrk(line, delims) != NULL)
  130.             {
  131.                 int pos = 1, del, lastdel = 0;
  132.                 char *next = NULL;
  133.  
  134.                 while (errno == 0 && pos < MAXLIST && (del = nextfield(out, lin
  135. e, &next)) != EOF)
  136.                 {
  137.                     if (use[pos])
  138.                     {
  139.                         if (lastdel) fputc(lastdel, stdout);
  140.                         lastdel = del;
  141.                         if (errno == 0) fputs(out, stdout);
  142.                     }
  143.                     pos++;
  144.                 }
  145.                 if (errno == 0) fputc('\n', stdout);
  146.             }
  147.             else if (!suppress)
  148.             {
  149.                 fputs(line, stdout);
  150.                 fputc('\n', stdout);
  151.             }
  152.     }
  153.     if (errno != 0)
  154.     {
  155.         perror("cut failed");
  156.         err = ERROR;
  157.     }
  158. }
  159.  
  160. char *c_str(char *to, char *from, int cnt)
  161. {
  162.     char *ret = to;
  163.  
  164.     while (from[0] && --cnt)
  165.     {
  166.         if (from[0] == '\\' && from[1])
  167.         {
  168.             switch (*++from)
  169.             {
  170.                 case 'n':
  171.                     *to++ = '\n';
  172.                     break;
  173.                 case 'r':
  174.                     *to++ = '\r';
  175.                     break;
  176.                 case 't':
  177.                     *to++ = '\t';
  178.                     break;
  179.                 case 'b':
  180.                     *to++ = '\b';
  181.                     break;
  182.                 case 'f':
  183.                     *to++ = '\f';
  184.                     break;
  185.                 case 'x':
  186.                     if (isxdigit(from[1]) && isxdigit(from[2]))
  187.                     {
  188.                         *to++ = hexdigit(from[1]) << 4 | hexdigit(from[2]);
  189.                         from += 2;
  190.                     }
  191.                     else
  192.                         fputs("Bad hex char\n", stderr);
  193.                     break;
  194.                 case '0': case '1': case '2': case '3':
  195.                 case '4': case '5': case '6': case '7':
  196.                     if (isoctal(from[1]) && isoctal(from[2]))
  197.                     {
  198.                         *to++ = (from[0] - '0') << 6 | (from[1] - '0') << 3 |
  199.                                 (from[2] - '0');
  200.                         from += 2;
  201.                     }
  202.                     else
  203.                         fputs("Bad octal char\n", stderr);
  204.                     break;
  205.                 default:
  206.                     *to++ = *from;
  207.                     break;
  208.             }
  209.             from++;
  210.         }
  211.         else
  212.             *to++ = *from++;
  213.     }
  214.     *to = '\0';
  215.     return ret;
  216. }
  217.  
  218. int analyse_range(char *range)
  219. {
  220.     int last, first;
  221.  
  222.     range = stpblk(range);
  223.  
  224.     if (*range == '-') first = 1;
  225.     else
  226.     {
  227.         if (!isdigit(*range)) return FALSE;
  228.         range += stcd_i(range, &first);
  229.         range = stpblk(range);
  230.     }
  231.     if (*range == '-')
  232.     {
  233.         range++;
  234.         if (isdigit(*range))
  235.             range += stcd_i(range, &last);
  236.  
  237.         else
  238.             last = MAXLIST - 1;
  239.     }
  240.     else last = first;
  241.  
  242.     if (*stpblk(range) == '\0' && first > 0 && first <= last && last < MAXLIST)
  243.      
  244.     {
  245.         int i;
  246.  
  247.         for (i = first; i <= last; i++) use[i] = TRUE;
  248.  
  249.         return TRUE;
  250.     }
  251.     else
  252.         return FALSE;
  253. }
  254.  
  255. int analyse_list(char *list)
  256. {
  257.     int i;
  258.     char *end;
  259.  
  260.     for (i = 1; i < MAXLIST; i++) use[i] = FALSE;
  261.  
  262.     while (end = strchr(list, ','))
  263.     {
  264.         *end = '\0';
  265.         if (!analyse_range(list)) return FALSE;
  266.         list = end + 1;
  267.     }
  268.     return analyse_range(list);
  269. }
  270.  
  271. void main(int argc, char **argv)
  272. {
  273.     int usage = TRUE, ch;
  274.  
  275.     /* Setup stdout */
  276.     if (IsInteractive(chkufb(fileno(stdout))->ufbfh))
  277.         setvbuf(stdout, NULL, _IOLBF, _bufsiz);
  278.  
  279.     /* Analyse command line */
  280.     while (usage && (ch = getoptx(argc, argv, "c:d:f:su")) != EOF)
  281.     {
  282.         switch (ch)
  283.         {
  284.             case 'c':
  285.                 column = TRUE;
  286.                 usage = analyse_list(optarg);
  287.                 break;
  288.             case 'd':
  289.                 delim = TRUE;
  290.                 c_str(delims, optarg, MAXDELIM);
  291.                 break;
  292.             case 'f':
  293.                 field = TRUE;
  294.                 usage = analyse_list(optarg);
  295.                 break;
  296.             case 's':
  297.                 suppress = TRUE;
  298.                 break;
  299.             case 'u':
  300.                 unique = TRUE;
  301.                 break;
  302.             default:
  303.                 usage = FALSE;
  304.                 break;
  305.         }
  306.     }
  307.     if (!(column && !(delim || field || suppress) || field && !column))
  308.         usage = FALSE;
  309.  
  310.     if (!usage)
  311.     {
  312.         fprintf(stderr, "Usage:\t%s -clist [files]\n\t%s -flist [-dchar] [-su]
  313. [files]\n", argv[0], argv[0]);
  314.         err = WARN;
  315.     }
  316.     else
  317.         /* Do cut */
  318.         if (argc == optind)
  319.             cut(stdin);
  320.         else
  321.         {
  322.             int i;
  323.  
  324.             for (i = optind; err < ERROR && i < argc; i++)
  325.             {
  326.                 FILE *f = fopen(argv[i], "r");
  327.  
  328.                 if (!f)
  329.                 {
  330.                     fprintf(stderr, "Error opening %s", argv[i]);
  331.                     perror("");
  332.                     err = WARN;
  333.                 }
  334.                 else
  335.                 {
  336.                     cut(f);
  337.                     fclose(f);
  338.                 }
  339.             }
  340.         }
  341.     exit(err);
  342. }
  343.